#include "vanila/dsobject.h"
#include <map>

namespace vanila
{
ObjectDictionary::ObjectDictionary(): 
    Object{ObjectType::DICTIONARY}, _dict{}
{}

ObjectDictionary::ObjectDictionary(std::map<Value, Value> dict):
    Object{ObjectType::DICTIONARY}, _dict{ std::move(dict) }
{}

//! \brief print object list
//! \param[in] callStr wheather call '__str__' method to print
void ObjectDictionary::print(bool callStr) const
{
    static_cast<void>(callStr);
    std::cout << '{';

    bool firstPair = true;
    for (auto iter = this->_dict.cbegin(); iter != this->_dict.cend(); ++iter)
    {
        if (!firstPair)
            std::cout << ", ";

        iter->first.print();
        std::cout << ": ";
        iter->second.print();

        firstPair = false;
    }

    std::cout << '}';
}

//! \brief wheather this == that
bool ObjectDictionary::equal(const Object* that) const
{
    const ObjectDictionary* other = that->asDictionary();
    if (this->_dict.size() != other->_dict.size())
        return false;
    
    auto iter1 = this->_dict.cbegin();
    auto iter2 = other->_dict.cbegin();
    for (size_t i = 0; i < this->_dict.size(); ++i)
    {
        if ( !iter1->first.equal(iter2->first) || !iter1->second.equal(iter2->second) )
            return false;
        iter1++;
        iter2++;
    }

    return true;
}

//! \brief get the value by specify key
//! \param[in] key the specify key
//! \param[out] value the value reference 
//! \return true if the key exits
bool ObjectDictionary::get(const Value& key, Value& value)
{
    auto iter = this->_dict.find(key);
    if (iter == this->_dict.end())
        return false;
    value = iter->second;
    return true;
}

//! \brief set the value by specify key
//! \param[in] key specify key
//! \param[in] value new value
void ObjectDictionary::set(const Value& key, const Value& value)
{
    this->_dict[key] = value;
}

}